#include "variant.h"
#include <sstream>
#include <iostream>

Variant::Variant(string value)
{
    setValue(value);
}

Variant::Variant(int value)
{
    setValue(value);
}

Variant::Variant(float value)
{
    setValue(value);
}

Variant::Variant(vector<string> value)
{
    setValue(value);
}

Variant::Variant(vector<int> value)
{
    setValue(value);
}

Variant::Variant(vector<float> value)
{
    setValue(value);
}

string Variant::replaceAll(string str, const string& from, const string& to)
{
    string::size_type pos = str.find(from);
 
    while(pos < str.size())
    {
        str.replace( pos, from.size(), to );
        pos = str.find( from, pos + to.size() );
    }
    
    return str;
}

void Variant::setTokenized(const bool& tokenized)
{
    m_tokenized = tokenized;
}

bool Variant::tokenized()
{
    return m_tokenized;
}

string Variant::tokenize()
{
    std::stringstream ss;
    switch(m_type)
    {
        case String:
            if(m_tokenized)
                return m_stringValue;
            else
                return '\"' + replaceAll(m_stringValue, "\"", "\\\"") + '\"';
        
        case Int:
            ss << m_intValue;
            return ss.str();
        
        case Float:
            ss << m_floatValue;
            return ss.str();
        
        case StringVector:
            for (vector<string>::iterator it = m_stringVectorValue.begin();
                it != m_stringVectorValue.end(); ++it )
            {
                if(it != m_stringVectorValue.begin())
                    ss << ",";
                ss << '\"' << replaceAll(*it, "\"", "\\\"") << '\"';
            }
            return ss.str();
        
        case IntVector:
            for (vector<int>::iterator it = m_intVectorValue.begin();
                it != m_intVectorValue.end(); ++it )
            {
                if(it != m_intVectorValue.begin())
                    ss << ",";
                ss << *it;
            }
            return ss.str();
        
        case FloatVector:
            for (vector<float>::iterator it = m_floatVectorValue.begin();
                it != m_floatVectorValue.end(); ++it )
            {
                if(it != m_floatVectorValue.begin())
                    ss << ",";
                ss << *it;
            }
            return ss.str();
        
        // Here be dragons
        default:
            return "";
    }
}

Variant Variant::parseTokens(const string& str, const Type& type)
{
    istringstream iss(str);
    string::size_type pos = 0;
    string::size_type strBegin = 0;
    int state = 0;
    string stringRet;
    vector<string> stringVectorRet;
    vector<int> intVectorRet;
    vector<float> floatVectorRet;
    
    switch(type)
    {
        case String:
            if(str.size() < 3)
                return Variant("");
            //Remove " from begining and end and unescape
            else {
                stringRet = str.substr(1, str.size() - 2);
                stringRet = replaceAll(stringRet, "\\\"", "\"");
                return Variant(stringRet);
            }
        
        case Int:
            int intRet;
             // string to int
            iss >> intRet;
            return Variant(intRet);
        
        case Float:
            float floatRet;
             // string to float
            iss >> floatRet;
            return Variant(floatRet);
            
        case StringVector:
            while(pos < str.size())
            {
                // beginning of string
                if(state == 0 && str[pos] == '\"')
                {
                    state = 1;
                    strBegin = pos + 1;
                    pos = str.find( "\"", pos + 1 );
                    pos = (pos < str.size()) ?  pos : str.size();
                // inside string, escaped "
                } else if(state == 1 && str[pos-1] == '\\')
                {
                    pos = str.find( "\"", pos + 1 );
                    pos = (pos < str.size()) ?  pos : str.size();
                // end of string
                } else if(state == 1 && str[pos-1] != '\\')
                {
                    string temp = str.substr(strBegin, pos - strBegin);
                    stringVectorRet.push_back(replaceAll(temp, "\\\"", "\""));
                    state = 0;
                    pos = str.find( "\"", pos + 1 );
                    pos = (pos < str.size()) ?  pos : str.size();
                }
            }
            return Variant(stringVectorRet);
    
        case IntVector:
            while(pos < str.size()) 
            {
                string::size_type posEnd = str.find(",", pos + 1 );
                posEnd = (posEnd < str.size()) ?  posEnd : str.size();
                string temp = str.substr(pos, posEnd - pos);
                pos = posEnd+1;
                istringstream iss2(temp);
                int tempInt;
                iss2 >> tempInt;
                intVectorRet.push_back(tempInt);
            }
            return Variant(intVectorRet);
        
        case FloatVector:
            while(pos < str.size())
            {
                string::size_type posEnd = str.find( ",", pos + 1 );
                posEnd = (posEnd < str.size()) ?  posEnd : str.size();
                string temp = str.substr(pos, posEnd - pos);
                cout << "cadena: " << temp << endl;
                pos = posEnd+1;
                istringstream iss2(temp);
                float tempFloat;
                iss2 >> tempFloat;
                floatVectorRet.push_back(tempFloat);
            }
            return Variant(floatVectorRet);
    }
    return Variant("");
}

void Variant::setValue(string value)
{
    m_type = String;
    m_stringValue = value;
}

void Variant::setValue(int value)
{
    m_type = Int;
    m_intValue = value;
}

void Variant::setValue(float value)
{
    m_type = Float;
    m_floatValue = value;
}

void Variant::setValue(vector<string> value)
{
    m_type = StringVector;
    m_stringVectorValue = value;
}

void Variant::setValue(vector<int> value)
{
    m_type = IntVector;
    m_intVectorValue = value;
}

void Variant::setValue(vector<float> value)
{
    m_type = FloatVector;
    m_floatVectorValue = value;
}

string Variant::toString() const
{
    return m_stringValue;
}

int Variant::toInt() const
{
    return m_intValue;
}

float Variant::toFloat() const
{
    return m_floatValue;
}

vector<string> Variant::toStringVector() const
{
    return m_stringVectorValue;
}

vector<int> Variant::toIntVector() const
{
    return m_intVectorValue;
}

vector<float> Variant::toFloatVector() const
{
    return m_floatVectorValue;
}

Variant::Type Variant::type() const
{
    return m_type;
}
